/**
 * 
 */
package com.cloudcast.client.controller;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.cloudcast.client.presenter.Presenter;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.google.gwt.event.shared.HandlerManager;

/**
 * @author Samuel García Martínez <in0de>
 *
 */
public abstract class MultiPresenterController extends AbstractController {
	
	private Map<String, LayoutContainer> containers;
	
	public MultiPresenterController(Controller parentController, HandlerManager eventBus) {
		super(parentController, eventBus);
		
		this.containers = new HashMap<String, LayoutContainer>();
		registerContainers(this.containers);
	}
	
	public abstract void registerContainers(Map<String, LayoutContainer> containers);
	
	public void invokeView(String viewId) throws ControllerException {
		Responsible responsible = getResponsible(viewId);
		
		if(responsible == null)
			throw new ControllerException(this, "Not responsible found for token " + viewId);		
		
		Boolean invokeControllerPresenter = getParent() != null && !getParent().isActualResponsible(this);
				
		if(invokeControllerPresenter)
			invokeControllerPresenter();
		
		doInvokeView(viewId, responsible);
		
		this.setActualResponsible(responsible);
	}
	
	protected void doInvokeView(String viewId, Responsible responsible) throws ControllerException {
		
		if(responsible instanceof Controller) 
			((Controller)responsible).invokeView(viewId);
		else if(responsible instanceof Presenter) 
			((Presenter)responsible).go(getContainer(viewId));
		else
			throw new ControllerException(this, "Unknown responsible type for token " + viewId);
	}

	@Override
	public void bind(Controller controller) {
		String token = controller.getActualViewId();
		
		Set<String> tokens = getResponsibles().keySet();
		for(String thisToken : tokens) {
			if(token.equals(thisToken))
				continue;
			
			try {
				doInvokeView(thisToken, getResponsibles().get(thisToken));
			} catch (ControllerException e) {
				/* TODO: error management */
			}
		}
		
		doBind(controller);
	}
	
	protected abstract void doBind(Controller controller); 
	
	protected LayoutContainer getContainer(String viewId) {
		return this.containers.get(viewId);
	}
	
	protected Map<String, LayoutContainer> getContainers() {
		return this.containers;
	}	
}
